package com.xuzhiguang.lightnat.server.core.server.transfer.handler;

import com.xuzhiguang.lightnat.common.message.NatMessage;
import com.xuzhiguang.lightnat.common.message.transfer.TransferAuthenticationRequest;
import com.xuzhiguang.lightnat.common.message.transfer.TransferAuthenticationResponse;
import com.xuzhiguang.lightnat.common.util.IdUtil;
import com.xuzhiguang.lightnat.server.core.client.NatClient;
import com.xuzhiguang.lightnat.server.core.client.NatClientService;
import com.xuzhiguang.lightnat.server.core.server.transfer.TransferChannelManager;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@ChannelHandler.Sharable
public class AuthenticationHandler extends SimpleChannelInboundHandler<NatMessage> {

    private final NatClientService natClientService;

    public AuthenticationHandler(NatClientService natClientService) {
        this.natClientService = natClientService;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, NatMessage msg) throws Exception {
        try {
            if (msg.getBody() instanceof TransferAuthenticationRequest) {
                TransferAuthenticationRequest request = (TransferAuthenticationRequest) msg.getBody();

                NatClient natClient = natClientService.getNatClient(request.getToken());

                TransferAuthenticationResponse response = new TransferAuthenticationResponse();

                if (natClient != null && natClient.getExpireTime() > System.currentTimeMillis()) {
                    long transferId = IdUtil.nextId();
                    TransferChannelManager.add(transferId, ctx.channel());
                    log.info("transfer auth success. transferId:{}", transferId);

                    response.setTransferId(transferId);
                    response.setSuccess(true);

                } else {
                    log.warn("transfer auth fail. token:{}", request.getToken());
                    response.setSuccess(false);
                    response.setErrMsg("invalid token");
                }

                ctx.channel().writeAndFlush(new NatMessage(response, msg.getHeader().getRequestId()));
                if (!response.getSuccess()) {
                    ctx.close();
                }

            } else {
                log.warn("expect first msg is auth request");
                ctx.close();
            }
        } finally {
            ctx.pipeline().remove(this);
        }
    }


}
